﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using log4net;
using log4net.Repository.Hierarchy;
using log4net.Config;
using System.IO;
using System.Xml.Linq;
using System.Xml;
using System.Web;

namespace MyAlbum.Logging
{
    public class Log4Net : ILogger
    {
        #region ILogger Members
        private static ILog _logger;

        static Log4Net()
        {

        }
        private ILog Logger
        {
            get
            {
                if (_logger == null)
                {
                    var console = new XElement("appender", new XAttribute("name", "Console"),
                                new XAttribute("type", "log4net.Appender.ConsoleAppender"),
                                new XElement("layout", new XAttribute("type", "log4net.Layout.PatternLayout"),
                                    new XElement("conversionPattern", new XAttribute("value", "%date%5level  (%file:%line) - %message%newline"))));
                    var tracer = new XElement("appender", new XAttribute("name", "RollingFile"),
                                new XAttribute("type", "log4net.Appender.RollingFileAppender"),
                                new XElement("file", new XAttribute("value", GetTraceFileName())),
                                new XElement("datePattern", new XAttribute("value", "yyyyMMdd")),

                                new XElement("appendToFile", new XAttribute("value", "true")),
                                new XElement("maximumFileSize", new XAttribute("value", "500KB")),
                                new XElement("maxSizeRollBackups", new XAttribute("value", "2")),
                                new XElement("layout", new XAttribute("type", "log4net.Layout.PatternLayout"),
                                    new XElement("conversionPattern", new XAttribute("value", "%date%level - %message%newline"))));

                    var errors = new XElement("appender", new XAttribute("name", "ErrorRollingFile"),
                               new XAttribute("type", "log4net.Appender.RollingFileAppender"),
                               new XElement("filter", new XAttribute("type", "log4net.Filter.LevelRangeFilter"), new XElement("levelMin", "WARN"), new XElement("levelMax", "FATAL")),
                               new XElement("file", new XAttribute("value", GetErrorsFileName())),
                               new XElement("datePattern", new XAttribute("value", "yyyyMMdd")),
                               new XElement("appendToFile", new XAttribute("value", "true")),
                               new XElement("maximumFileSize", new XAttribute("value", "500KB")),
                               new XElement("maxSizeRollBackups", new XAttribute("value", "2")),
                               new XElement("layout", new XAttribute("type", "log4net.Layout.PatternLayout"),
                                   new XElement("conversionPattern", new XAttribute("value", "%date%level - %message%newline"))));

                    var smtp = new XElement("appender", new XAttribute("name", "SmtpAppender"),
                       new XAttribute("type", "log4net.Appender.SmtpAppender"),
                       new XElement("filter", new XAttribute("type", "log4net.Filter.LevelRangeFilter"), new XElement("levelMin", "ERROR"), new XElement("levelMax", "FATAL")),
                       new XElement("to", new XAttribute("value", this.Email)),
                       new XElement("from", new XAttribute("value", this.SenderEmail)),
                       new XElement("subject", new XAttribute("value", "Error on site")),
                         new XElement("username", new XAttribute("value", this.SmtpUsername)),
                           new XElement("password", new XAttribute("value", this.SmtpPassword)),
        new XElement("smtpHost", new XAttribute("value", this.SmtpHost)),
            new XElement("bufferSize", new XAttribute("value", "512")),
            new XElement("lossy", new XAttribute("value", "true")),
            new XElement("evaluator", new XAttribute("type", "log4net.Core.LevelEvaluator"),
                new XElement("threshold", new XAttribute("value", "ERROR"))),
            new XElement("layout", new XAttribute("type", "log4net.Layout.PatternLayout"),
               new XElement("conversionPattern", new XAttribute("value", "%newline%date [%thread] %-5level [%property{NDC}] - %message%newline%newline%newline"))));
                    var levels = new XElement("root", new XElement("level", new XAttribute("value", "DEBUG")),
                                                new XElement("appender-ref", new XAttribute("ref", "Console")),
                                                new XElement("appender-ref", new XAttribute("ref", "SmtpAppender")),
                                                new XElement("appender-ref", new XAttribute("ref", "ErrorRollingFile")),
                                                new XElement("appender-ref", new XAttribute("ref", "RollingFile")));
                    var root = new XElement("log4net");
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        root.Add(console);
                    }
                    if (this.EnableTrace)
                    {
                        root.Add(tracer);
                    }

                    if (this.EmailOnErrors)
                    {
                        try
                        {
                            root.Add(smtp);
                            //if some values are null an exception will be thrown
                        }
                        catch { }
                    }
                    root.Add(errors);
                    root.Add(levels);
                    XDocument doc = new XDocument(new XDeclaration("1.0", "utf-8", "true"), root);


                    XmlDocument doc1 = new XmlDocument();
                    StringWriter conf = new StringWriter();
                    doc.Save(conf);
                    //don't ask why, but it seems the constructor has a problem when I pass the exact xml
                    //string I pass to the document here, it throws invalid xml exception, so I just pass
                    //a ready document
                    doc1.LoadXml(conf.ToString());
                    //     log4net.Config.BasicConfigurator.Configure();
                    XmlConfigurator.Configure(doc1.DocumentElement);
                    _logger = LogManager.GetLogger(typeof(Log4Net));
                }
                return _logger;
            }
        }
        private string GetErrorsFileName()
        {
            return GetFilePath(ILogger.ErrorsFileName);

        }

        private string GetFilePath(string fileName)
        {
            string directory = HttpContext.Current == null ? Directory.GetCurrentDirectory() : HttpContext.Current.Server.MapPath("~/App_Data/Logs");
            if (!Directory.Exists(directory))
            {
                Directory.CreateDirectory(directory);
            }
            return Path.Combine(directory, fileName);
        }
        private string GetTraceFileName()
        {
            return GetFilePath(ILogger.TraceFileName);
        }
        public override void LogError(Exception e1)
        {
            LogError(e1, null);
        }

        public override void LogError(string message)
        {
            LogError(null, message);
        }

        public override void LogError(Exception e1, string message)
        {
            Logger.Error(message, e1);
        }

        public override void Trace(object data)
        {
            Logger.Debug(data);
        }

        public override void Info(string message)
        {
            Logger.Info(message);
        }


        public override void Warning(string message)
        {
            Logger.Warn(message);
        }

        #endregion
    }
}
